<template>
  <view class="ve-form-item">
    <view :class="['ve-form-item__body', labelPosition === 'left' ? 'row' : 'column']" @tap="clickHandler">
      <!-- label -->
      <slot name="label">
        <view
          class="ve-form-item__body__left"
          v-if="required || label || $slots['label-extra']"
          :style="{
            width: addUnit(labelWidth),
            marginBottom: labelPosition === 'left' ? 0 : '24rpx',
          }"
        >
          <view class="ve-form-item__body__left__content">
            <text
              class="ve-form-item__body__left__content__label"
              :class="disabled ? 've-form-item__body__left__content__label__disabled' : ''"
            >
              {{ label }}<text v-if="required" class="ve-form-item__body__left__content__required">*</text>
            </text>
            <view class="ve-form-item__body__left__content__icon" v-if="$slots.icon || $slots.content || labelTooltipContent">
              <template v-if="$slots.icon">
                <slot name="icon"></slot>
              </template>
              <template v-else>
                <ve-tooltip :content="labelTooltipContent" :placement="labelTooltipPosition">
                  <template v-if="$slots.content" #content>
                    <slot name="content"></slot>
                  </template>
                  <text class="iconfont ve-icon-help" style="font-size: 34rpx"></text>
                </ve-tooltip>
              </template>
            </view>
          </view>
          <view class="ve-label-extra">
            <slot name="label-extra"></slot>
          </view>
        </view>
      </slot>
      <!-- content -->
      <!-- 左右布局 -->
      <view class="ve-form-item__body__right" v-if="labelPosition === 'left'">
        <view class="ve-form-item__body__right__content">
          <view class="ve-form-item__body__right__content__slot" :style="rightItemStyle">
            <slot />
          </view>
          <view class="ve-form-item__body__right__content__unit" v-if="unit && unit != ''">
            <block v-if="unit == 'arrowRight'">
              <ve-icon v-if="disabled" name="arrow_right_2" size="25" />
              <ve-icon v-else name="arrow_right_0" size="32" />
            </block>
            <block v-else>{{ unit }}</block>
          </view>
        </view>
        <view class="right-content" v-if="$slots.rightContent">
          <slot name="rightContent" />
        </view>
        <view class="left-content" v-if="$slots.leftContent">
          <slot name="leftContent" />
        </view>
      </view>
      <!-- 上下布局 -->
      <view class="ve-form-item__body__right" v-else>
        <view class="ve-form-item__body__right__content">
          <slot />
        </view>
      </view>
    </view>
    <!-- footer -->
    <view class="ve-form-item_footer" v-if="$slots.footer">
      <slot name="footer"></slot>
      <view style="height: 32rpx; width: 100%"></view>
    </view>
    <!-- error 信息 -->
    <slot name="error">
      <text v-if="!!message" class="ve-form-item__body__right__message">{{ message }}</text>
    </slot>
    <!-- 底部 -->
    <view
      v-if="borderBottom"
      class="ve-form-item__border"
      :style="{
        'margin-top': message ? '5px' : 0,
      }"
    >
    </view>
  </view>
</template>

<script>
  import { getProperty, $parent, setProperty } from '../../utils/form_tools'
  export default {
    name: 've-form-item',
    // #ifdef MP-WEIXIN
    // 将自定义节点设置成虚拟的，更加接近Vue组件的表现，能更好的使用flex属性
    options: {
      virtualHost: true,
    },
    // #endif
    props: {
      // input的label提示语
      label: {
        type: String,
        default: '',
      },
      // 绑定的值
      prop: {
        type: String,
        default: '',
      },
      // 是否显示左边的必填星号，只作显示用
      required: {
        type: Boolean,
        default: false,
      },
      // 是否显示表单域的下划线边框
      borderBottom: {
        type: Boolean,
        default: true,
      },
      // label的位置，left-左边，top-上边
      labelPosition: {
        type: String,
        default: 'left',
      },
      // value的位置，left-左边，right-上边
      valuePosition: {
        type: String,
        default: 'right',
      },
      // label的宽度，单位px 数值 | auto
      labelWidth: {
        type: [String, Number],
        default: 'auto',
      },
      // help 内容
      labelTooltipContent: {
        type: String,
        default: '',
      },
      labelTooltipPosition: {
        type: String,
        default: 'top-start',
      },
      // 右侧的单位
      unit: {
        type: [String],
        default: '',
      },
      disabled: {
        type: Boolean,
        default: false,
      },
    },
    data() {
      return {
        // 错误提示语
        message: '',
        rightItemStyle: {
          justifyContent: this.valuePosition === 'left' ? 'flex-start' : 'flex-end',
        },
      }
    },
    mounted() {
      this.init()
    },
    methods: {
      /**
       * 验证十进制数字
       */
      isNumber(value) {
        return /^[+-]?(\d+\.?\d*|\.\d+|\d\.\d+e\+\d+)$/.test(value)
      },
      /**
       * @description 添加单位，如果有rpx，upx，%，px等单位结尾或者值为auto，直接返回，否则加上px单位结尾
       * @param {string|number} value 需要添加单位的值
       * @param {string} unit 添加的单位名 比如px
       */
      addUnit(value = 'auto', unit = 'px') {
        value = String(value)
        // 用uView内置验证规则中的number判断是否为数值
        return this.isNumber(value) ? `${value}${unit}` : value
      },
      init() {
        // 父组件的实例
        this.updateParentData()
        if (!this.parent) {
          console.log('ve-form-item需要结合ve-form组件使用')
        }
      },
      getParentData(parentName = '') {
        // 避免在created中去定义parent变量
        if (!this.parent) this.parent = {}
        // 这里的本质原理是，通过获取父组件实例(也即类似u-radio的父组件u-radio-group的this)
        // 将父组件this中对应的参数，赋值给本组件(u-radio的this)的parentData对象中对应的属性
        // 之所以需要这么做，是因为所有端中，头条小程序不支持通过this.parent.xxx去监听父组件参数的变化
        // 此处并不会自动更新子组件的数据，而是依赖父组件u-radio-group去监听data的变化，手动调用更新子组件的方法去重新获取
        this.parent = $parent.call(this, parentName)
        if (this.parent.children) {
          // 如果父组件的children不存在本组件的实例，才将本实例添加到父组件的children中
          this.parent.children.indexOf(this) === -1 && this.parent.children.push(this)
        }
      },
      // 获取父组件的参数
      updateParentData() {
        // 此方法写在mixin中
        this.getParentData('ve-form')
      },
      // 移除ve-form-item的校验结果
      clearValidate() {
        this.message = null
      },
      // 清空当前的组件的校验结果，并重置为初始值
      resetField() {
        // 找到原始值
        const value = getProperty(this.parent.originalModel, this.prop)
        // 将u-form的model的prop属性链还原原始值
        setProperty(this.parent.model, this.prop, value)
        // 移除校验结果
        this.message = null
      },
      // 点击组件
      clickHandler() {
        this.$emit('click')
      },
    },
  }
</script>

<style lang="scss" scoped>
  @mixin flex($direction: row) {
    /* #ifndef APP-NVUE */
    display: flex;
    /* #endif */
    flex-direction: $direction;
  }
  .ve-form-item {
    @include flex(column);
    font-size: 28rpx;
    color: #191c27;

    &__body {
      @include flex;
      padding: 32rpx 0;
      position: relative;
      align-items: flex-start;

      &__left {
        @include flex;
        // flex: 1;
        flex-shrink: 0;
        align-items: center;

        &__content {
          position: relative;
          @include flex;
          align-items: center;
          padding-right: 24rpx;
          flex: 1;

          &__label {
            @include flex;
            align-items: center;
            color: #303133;
            font-size: 30rpx;

            &__disabled {
              color: #8491a8;
            }
          }

          &__required {
            color: #f53f3f;
            line-height: 1;
            vertical-align: middle;
            font-size: 40rpx;
          }

          &__icon {
            margin-left: 16rpx;
            line-height: 1;
          }
        }
      }

      &__right {
        width: 100%;
        flex: 1;

        &__content {
          @include flex;
          align-items: center;
          word-break: break-all;
          flex: 1;

          &__slot {
            flex: 1;
            /* #ifndef MP */
            @include flex;
            align-items: center;
            /* #endif */
            ::v-deep input {
              font-size: 28rpx;
              text-align: right;
              justify-content: flex-end;
              line-height: normal;
            }
          }
          &__unit {
            margin-left: 6rpx;
            font-size: 28rpx;
            color: #191c27;
            display: flex;
            align-items: center;
            ve-svg-icon {
              @include flex;
            }
          }
        }

        .right-content {
          margin-top: 24rpx;
        }
        .left-content {
          position: absolute;
          bottom: 34rpx;
          left: 145rpx;
        }

        &__message {
          width: 100%;
          text-align: right;
          font-size: 26rpx;
          color: #f53f3f;
          line-height: 44rpx;
          margin-top: -16rpx;
          padding-bottom: 16rpx;
        }
      }
    }

    // labelPosition 为 top 时 布局优化
    &__body.column {
      display: block;
      .ve-form-item__body__left {
        width: 100% !important;
      }
      .ve-form-item__body__right {
        width: 100%;
      }
    }

    .error {
      position: absolute;
      right: 6rpx;
      bottom: -6rpx;
    }

    &__border {
      height: 1px;
      width: 100%;
      background: rgba(216, 216, 216, 0.3);
    }
  }
</style>
